package com.block.service;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Base64Util {

        public static String code = "UTF-8";
        public static String keyDes = "c1977cdb4e1d468d1bbabb4b7891b5ad";
        public static String keyAes = "c1977cdb4e1d468d1bbabb4b7891b5ad";

        public static String encrypt(String data, String secretKey) {
                try {
                        byte[] encrpyted = tripleDES(Cipher.ENCRYPT_MODE, data.getBytes(code), secretKey.getBytes());
                        byte[] encoded = Base64.encodeBase64(encrpyted); // Base64 编码
                        return new String(encoded);
                } catch (UnsupportedEncodingException e) {
                        throw new RuntimeException(e);
                }
        }

        public static String decrypt(String data, String key) {
                try {
                        byte[] decoded = Base64.decodeBase64(data); // Base64 解码
                        byte[] decrypted = tripleDES(Cipher.DECRYPT_MODE, decoded, key.getBytes());// 3DES 解密
                        return new String(decrypted, code);
                } catch (UnsupportedEncodingException e) {
                        throw new RuntimeException(e);
                }
        }

        private static byte[] tripleDES(int opmode, byte[] data, byte[] secretKey) {
                return cipher("DESede", "DESede/CBC/PKCS5Padding", opmode, data, "4e1d468d1bbabb4b".getBytes(), secretKey);
        }

        private static byte[] cipher(String algorithm, String transformation, int opmode, byte[] data, byte[] iv, byte[] secretKey) {
                try {
                        Key key = SecretKeyFactory.getInstance(algorithm).generateSecret(new DESedeKeySpec(secretKey));
                        IvParameterSpec spec = new IvParameterSpec(iv);
                        Cipher cipher = Cipher.getInstance(transformation);
                        cipher.init(opmode, key, spec);
                        return cipher.doFinal(data);
                } catch (InvalidKeyException | InvalidKeySpecException | NoSuchAlgorithmException
                        | NoSuchPaddingException
                        | IllegalBlockSizeException | BadPaddingException |
                        InvalidAlgorithmParameterException e) {
                        throw new RuntimeException(e);
                }
        }

        public static JSONObject getParam(String merchantNo, Date date){
                JSONObject map = new JSONObject();
                map.put("merchantNo", merchantNo);
//                map.put("timestamp", DateUtil.dateToStrNormal(date));
                map.put("reqId", UUID.randomUUID().toString().replaceAll("-", ""));
                return map;
        }

        public static String encryptAes(String data, String secretKey) {
                try {
                        byte[] encrpyted = tripleAes(Cipher.ENCRYPT_MODE, data.getBytes(code), secretKey.getBytes());
                        byte[] encoded = Base64.encodeBase64(encrpyted); // Base64 编码
                        return new String(encoded);
                } catch (UnsupportedEncodingException e) {
                        throw new RuntimeException(e);
                }
        }

        private static byte[] cipherAes(String algorithm, String transformation, int opmode, byte[] data, byte[] iv, byte[] secretKey) {
                try {
                        Cipher cipher = Cipher.getInstance(transformation);
                        SecretKeySpec keyspec = new SecretKeySpec(secretKey, algorithm);
                        IvParameterSpec ivspec = new IvParameterSpec(iv);  // CBC模式，需要一个向量iv，可增加加密算法的强度

                        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
                        byte[] encrypted = cipher.doFinal(data);
                        return encrypted;
                } catch (InvalidKeyException | NoSuchAlgorithmException
                                 | NoSuchPaddingException
                                 | IllegalBlockSizeException | BadPaddingException |
                                 InvalidAlgorithmParameterException e) {
                        throw new RuntimeException(e);
                }
        }

        private static byte[] tripleAes(int opmode, byte[] data, byte[] secretKey) {
                return cipherAes("AES", "AES/CBC/PKCS5Padding", opmode, data, "dxjf18129979469s".getBytes(), secretKey);
        }


        public static String decryptAes(String data, String key) throws Exception {
                try
                {
                        byte[] decoded = Base64.decodeBase64(data); // Base64 解码

                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
                        IvParameterSpec ivspec = new IvParameterSpec("dxjf18129979469s".getBytes());

                        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

                        byte[] original = cipher.doFinal(decoded);
                        String originalString = new String(original);
                        return originalString.trim();
                }
                catch (Exception e) {
                        e.printStackTrace();
                        return null;
                }
        }


        public static void main(String[] args) {
                try {
                        Map<String,String> map = new HashMap<>();
                        map.put("city","深圳市");
                        map.put("idCard","123");
                        map.put("phoneNo","321");
                        map.put("loanAmount","1");
                        map.put("profession","1");
                        map.put("salaryType","1");
                        map.put("socialSecurity","1");
                        JSONObject param = getParam("TEST0001", new Date());
                        String paramStr = JSONUtils.toJSONString(map);
                        String enctryt_data = "";
                        String data = "";
                        enctryt_data = encrypt(paramStr, keyDes);
                        param.put("data", enctryt_data);

                        System.out.println("===============DES模式 begin===============");
                        System.out.println("请求报文：" + JSONObject.toJSONString(param));
                        data = decrypt(enctryt_data, keyDes);
                        System.out.println("data解密结果:" + data);
                        System.out.println("===============DES模式 end===============");
                        System.out.println();
                        System.out.println();
                        System.out.println("===============AES/CBC/PKCS5Padding模式 begin===============");
                        enctryt_data = encryptAes(data, keyAes);
                        param.put("data", enctryt_data);
                        System.out.println("请求报文：" + JSONObject.toJSONString(param));
                        data = decryptAes(enctryt_data, keyAes);
                        System.out.println("data解密结果:" + data);
                        System.out.println("===============AES/CBC/PKCS5Padding模式 end===============");
                } catch (Exception e) {
                        e.printStackTrace();
                }
        }
}